﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CheckEncode
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryInfo rootDir = new DirectoryInfo("D:\\WorkSpace\\Development2\\Tetris");
            CheckDir(rootDir);
        }

        static void CheckDir(DirectoryInfo rootDirInfo)
        {
            // 遍历文件夹
            foreach (DirectoryInfo dirInfo in rootDirInfo.GetDirectories())
            {
                CheckDir(dirInfo);
                System.Console.WriteLine("\n");
            }

            // 遍历文件
            foreach (FileInfo fileInfo in rootDirInfo.GetFiles())
            {
                if (!filter(fileInfo.Name))
                {
                    continue;
                }
                FileStream fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
                BinaryReader binaryReader = new BinaryReader(fileStream);
                byte[] bytes = binaryReader.ReadBytes((int)fileStream.Length);
                if (bytes[0] == 0xEF && bytes[1] == 0xBB)
                {
                    System.Console.WriteLine("UTF8BOM " + fileInfo.FullName);
                }
                else if (bytes[0] == 0xFE && bytes[1] == 0xFF)
                {
                    System.Console.WriteLine("UnicBig " + fileInfo.FullName);
                }
                else if (bytes[0] == 0xFF && bytes[1] == 0xFE)
                {
                    System.Console.WriteLine("UnicSml " + fileInfo.FullName);
                }
                else
                {
                    if (IsUTF8Bytes(bytes))
                    {
                        System.Console.WriteLine("UTF8    " + fileInfo.FullName);
                    }
                    else
                    {
                        System.Console.WriteLine("ANSI    " + fileInfo.FullName);
                    }
                }
                binaryReader.Close();
                fileStream.Close();
            }
        }

        static bool filter(string fileName)
        {
            string[] temp = fileName.Split(new char[]{'.'});
            string extend = temp[temp.Length - 1];
            switch (extend)
            {
                case "cs":
                case "resx":
                case "c":
                case "h":
                case "rc":
                case "rc2":
                case "cpp":
                case "ts":
                case "pro":
                case "qrc":
                case "xml":
                case "java":
                case "properties":
                case "js":
                case "html":
                case "swift":
                case "plist":
                case "strings":
                case "storyboard":
                    return true;
            }
            return false;
        }

        // 判断是否是不带 BOM 的 UTF8 格式
        // utf-8编码规则：unicode 字符首字节的高八位有3个1（二进制），一共有3个连续这样的字节
        public static bool IsUTF8Bytes(byte[] data)
        {
            int charByteCounter = 1;    // 计算当前正分析的字符应还有的字节数
            byte curByte;               // 当前分析的字节
            bool hasUnicodeChar = false;
            for (int i = 0; i < data.Length; i++)
            {
                curByte = data[i];
                if (charByteCounter == 1)
                {
                    if (curByte >= 0x80 && curByte < 0xFF)
                    {
                        hasUnicodeChar = true;
                        // 判断当前
                        while (((curByte <<= 1) & 0x80) != 0)
                        {
                            charByteCounter++;
                        }
                        // 标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 
                        if (charByteCounter == 1)
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    // 若是UTF-8 此时第一位必须为1
                    if ((curByte & 0xC0) != 0x80)
                    {
                        return false;
                    }
                    charByteCounter--;
                }
            }
            if (charByteCounter > 1 || !hasUnicodeChar)
            {
                return false;
            }
            return true;
        }
    }
}
